#!/usr/bin/env python
#
#   Module for working with Google blogger
#
#   Based on Protocol 2.0
#   http://code.google.com/apis/blogger/docs/2.0/developers_guide_protocol.html
#
from subprocess import Popen, PIPE


class Blogger:

    # Authentication Error message
    auth_error_msg = ''
    # Authentication parameters
    auth_params = {}


    def __init__(self, blog_id):
        '''
        init
        '''
        self.blog_id = blog_id
        # Blog post URL
        self.blog_post_url = 'http://www.blogger.com/feeds/%s/posts/default' % self.blog_id
    
    def ClientLogin(self, username, password):
        '''
        ClientLogin authentication based on curl external tool
        
        Return:
            True if authentication is successful
            False if authentication is failed. In this case, the error code will be stored in auth_error_msg 
        
        More information about Google ClientLogin 
        http://code.google.com/apis/accounts/docs/AuthForInstalledApps.html#Request
        '''
        # To request an authentication token using the ClientLogin mechanism, send a POST request to the following URL
        auth_url = 'https://www.google.com/accounts/ClientLogin'
        opts = []
        
        # Specifying a Blogger Data API version = 2
        opts.append('-H "GData-Version: 2" ')
        
        # User Agent support 
        opts.append('-A "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3 (.NET CLR 3.5.30729)" ')
        
        # curl performs SSL certificate verification by default, using a "bundle"
        # of Certificate Authority (CA) public keys (CA certs). If the default
        # bundle file isn't adequate, you can specify an alternate file
        # using the --cacert option.
        #
        # If this HTTPS server uses a certificate signed by a CA represented in
        # the bundle, the certificate verification probably failed due to a
        # problem with the certificate (it might be expired, or the name might
        # not match the domain name in the URL).
        #
        # If you'd like to turn off curl's verification of the certificate, use
        # the -k (or --insecure) option.
        opts.append('-k ')

        # The POST body should contain a set of query parameters that look like parameters passed by an HTML form, 
        # using the application/x-www-form-urlencoded content type. These parameters are:
        #   Email           - The user's email address.
        #   Passwd          - The user's password.
        #   service         - The Blogger service name is blogger. (For other service names, see the service name list.)
        #   accountType     - This should always be set to GOOGLE when using the Blogger API. 
        #                   Failure to set this parameter will prevent access by users who also have a Google Apps account.
        #   source          - Identifies your client application. Should take the form 
        #                   companyName-applicationName-versionID. The examples use the name exampleCo-exampleApp-1. 
        #
        opts.append('-d "Email=%s&Passwd=%s&service=blogger&accountType=GOOGLE&source=pyGBlogger-0.1" ' % \
                    (username, password))
        
        curl = Popen(["curl", opts, auth_url], stdout=PIPE, stderr=PIPE)
        
        # authentification response
        auth_response_params = {}
        for line in curl.stdout.read().split('\n'):
            if len(line) == 0: continue
            auth_response_params[line.split('=')[0]] = line.split('=')[1]

        if 'Error' in auth_response_params.keys():
            self.auth_error_msg = auth_response_params['Error']
            return False
        else:
            self.auth_params = auth_response_params
            return True
        
    def bloglist(self, profile_id):
        '''
        provide a feed that lists the blogs for a particular user
        '''
        pass
    
    def create_post(self, title='', content='', categories=()):
        '''
        create and publish new blog entries, as well as creating drafts of entries
        '''
        # cURL options
        # --silent      Silent mode    
        # -i            Include protocol headers in the output
        curl_opts = ['--silent -i ']

        # entry: title + content + categories
        p_entry     = "<entry xmlns='http://www.w3.org/2005/Atom'>%s%s%s</entry>"
        p_title     = "<title type='text'>%s</title>" % title
        p_content   = "<content type='xhtml'>%s</content>" % content
        
        p_categories = ''
        for item in categories:
            p_categories += "<category scheme='http://www.blogger.com/atom/ns#' term='%s'/>" % item
        
        post = p_entry % (p_title, p_content, p_categories)
        curl_opts.append('-d "%s" ' % post)

        # HTTP Header
        # Specifying a Blogger Data API version = 2 
        curl_opts.append('-H "GData-Version:2" ')
        # Content-Type
        curl_opts.append('-H "Content-Type:application/atom+xml" ')
        # Authorization
        curl_opts.append('-H "Authorization:GoogleLogin auth=%s" ' % self.auth_params['Auth'])

        curl = Popen(["curl", curl_opts, self.blog_post_url], stdout=PIPE, stderr=PIPE)
        response = curl.stdout.read()
        if len(response) == 0: 
            return {'header': 'Failed', 'post': '', }
        else:
            data = response.split('\r\n\r\n', 1)
            return {'header': data[0], 'post': data[1], }
    
    def retrieve_post(self, blog_id):
        '''
        retrieve a list of blog posts, with and without parameters
        '''
        pass
    
    def update_post(self, post):
        '''
        update an existing blog post
        '''
        pass

    def deleting_post(self, post):
        '''
        delete a post
        '''
        pass
    
    def export_blog(self):
        '''
        export blog
        '''
        pass
    
    def import_blog(self):
        '''
        import blog
        '''
        pass
        
    
